// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/

// See page 136.

// The toposort program prints the nodes of a DAG in topological order.
package main

import (
	"fmt"
	"sort"
)

//!+table
// prereqs maps computer science courses to their prerequisites.
var prereqs = map[string][]string{
	"key1": {"data1"},
	"key2":   {"data2"},

	"key3": {
		"data1",
		"data3",
		"data4",
	},

	"key4":       {"data5"},
	"key5":             {"data1"},
	"key6":         {"data6"},
	"key7":      {"data5"},
	"key8":              {"data7"},
	"key9":     {"data1", "data4"},
	"key10": {"data1", "data4"},
}

//var prereqs = map[string][]string{
//	"algorithms": {"data structures"},
//	"calculus":   {"linear algebra"},

//	"compilers": {
//		"data structures",
//		"formal languages",
//		"computer organization",
//	},

//	"data structures":       {"discrete math"},
//	"databases":             {"data structures"},
//	"discrete math":         {"intro to programming"},
//	"formal languages":      {"discrete math"},
//	"networks":              {"operating systems"},
//	"operating systems":     {"data structures", "computer organization"},
//	"programming languages": {"data structures", "computer organization"},
//}

//!-table

//!+main
func main() {
	for i, course := range topoSort(prereqs) {
		fmt.Printf("%d:\t%s\n", i+1, course)
	}
	//topoSort(prereqs)
}

func topoSort(m map[string][]string) []string {
	var order []string
	seen := make(map[string]bool)
	var visitAll func(items []string)

	visitAll = func(items []string) {
		fmt.Println("visitAll:", items)
		for _, item := range items {
			if !seen[item] {
				seen[item] = true
				visitAll(m[item])
				order = append(order, item)
				fmt.Println("order:", order)
			}
		}
	}

	var keys []string
	for key := range m {
		keys = append(keys, key)
	}
	fmt.Println("before", keys)
	sort.Strings(keys)
	fmt.Println("after", keys)
	visitAll(keys)
	fmt.Println("order", order)
	return order
}

//!-main
